#include "UapStateMediaBearerSetupPend.h"
#include "UapStateMap.h"
#include "MgwGapProxy.h"
#include "MediaLibrary.h"
#include "ClientUapProxy.h"
#include "Trace.h"

namespace tsc
{
namespace sgw
{

using namespace tsc::common;

/*******************************************************************************
 *
 * Constructor
 *
 ******************************************************************************/
UapStateMediaBearerSetupPend::UapStateMediaBearerSetupPend() :
	UapStateBase("MediaBearerSetupPend")
{

} // UapStateMediaBearerSetupPend::UapStateMediaBearerSetupPend

/*******************************************************************************
 *
 * Destructor
 *
 ******************************************************************************/
UapStateMediaBearerSetupPend::~UapStateMediaBearerSetupPend()
{

} // UapStateMediaBearerSetupPend::~UapStateMediaBearerSetupPend


UapStateMediaBearerSetupPend* UapStateMediaBearerSetupPend::instance()
{
	static UapStateMediaBearerSetupPend mInstance;
	return &mInstance;
}

//===================================================================
void
UapStateMediaBearerSetupPend::handleEventUapConnectionReleaseReq(
    UapGenerator* uapGen,
    UapEventConnectionReleaseReq* event,
    EventData*& eventData)
{
    uapGen->cancelT643();

    TRACE(3, STR("Received UapConnectionRelease during bearer setup. Sending "
                 "GapMediaBearerRelease to MGW, connId=0x%x",
                 uapGen->getConnectionId()));

    if(!MgwGapProxy::instance().sendGapMediaBearerRelease(
            uapGen->getConnectionId()))
    {
        TRACE(1, STR("Failed to send GapMediaBearerRelease, connId=0x%x - "
                     "anyway deleting UapGenerator",
                     uapGen->getConnectionId()));
    }

    delete uapGen;
    uapGen = 0;

    EventData::deleteEvent(eventData);
}

//===================================================================
void
UapStateMediaBearerSetupPend::handleEventGapMediaBearerSetupCfm(
    UapGenerator* uapGen,
    UapEventGapMediaBearerSetupCfm* event,
    EventData*& eventData)
{
    uapGen->cancelT643();

    TRACE(4, STR("Received GAP MediaBearerSetupCfm, connId=0x%x, "
                 "serverMediaIpAddr=%s, serverMediaPort=%u",
                 uapGen->getConnectionId(),
                 event->getServerMediaAddress()->DebugString().c_str(),
                 event->getServerMediaPort()));

    uapGen->setServerMediaPort(event->getServerMediaPort());
    uapGen->setServerMediaAddress(event->getServerMediaAddress());

    if(!ClientUapProxy::instance().sendUapMediaBearerSetupCfm(*uapGen))
    {
        TRACE(1, STR("Failed to send UapMediaBearerSetupCfm to client, connId=0x%x - "
                     "releasing MediaBearer on MGW side",
                     uapGen->getConnectionId()));

        // failed to send CFM to UserClient so we need to tear down the
        // bearer on MGW side
        if(!MgwGapProxy::instance().sendGapMediaBearerRelease(
                uapGen->getConnectionId()))
        {
            TRACE(1, STR("Failed to send GapMediaBearerRelease to MGW, connId=0x%x",
                         uapGen->getConnectionId()));
        }

        uapGen->setServerMediaPort(0);
        uapGen->changeState(UapStateMap::mStateConnected);
    }
    else
    {
        TRACE(4, STR("Sent UapMediaBearerSetupCfm, connId=0x%x",
                     uapGen->getConnectionId()));
        uapGen->changeState(UapStateMap::mStateMediaTransmission);
    }

    EventData::deleteEvent(eventData);
}

//===================================================================
void
UapStateMediaBearerSetupPend::handleEventGapMediaBearerSetupRej(
    UapGenerator* uapGen,
    UapEventGapMediaBearerSetupRej* event,
    EventData*& eventData)
{
    uapGen->cancelT643();

    TRACE(4, STR("Received GAP MediaBearerSetupRej, connId=0x%x, "
                 "cause=%u",
                 uapGen->getConnectionId(),
                 event->getCause()));

    if(!ClientUapProxy::instance().sendUapMediaBearerSetupRej(
            uapGen->getConnectionId(),
            UserApplicationPart::CAUSE_UNSPECIFIED))
    {
        TRACE(1, STR("Failed to send UapMediaBearerSetupRej to client, connId=0x%x",
                     uapGen->getConnectionId()));
    }

    // clear parameters stored after reception of MediaBearerSetupReq
    uapGen->setClientMediaPort(0);
    uapGen->setMediaItemId(MediaLibrary::INVALID_MEDIA_ITEM_ID);

    uapGen->changeState(UapStateMap::mStateConnected);

    EventData::deleteEvent(eventData);
}

//===================================================================
void
UapStateMediaBearerSetupPend::handleEventT643Expired(
    UapGenerator* uapGen,
    UapEventT643Expired* event,
    EventData*& eventData)
{
    if(!ClientUapProxy::instance().sendUapMediaBearerSetupRej(
            uapGen->getConnectionId(),
            UserApplicationPart::CAUSE_UNSPECIFIED))
    {
        TRACE(1, STR("Failed to send UapMediaBearerSetupRej to client, connId=0x%x",
                     uapGen->getConnectionId()));
    }

    // clear parameters stored after reception of MediaBearerSetupReq
    uapGen->setClientMediaPort(0);
    uapGen->setMediaItemId(MediaLibrary::INVALID_MEDIA_ITEM_ID);

    uapGen->changeState(UapStateMap::mStateConnected);

    EventData::deleteEvent(eventData);
}

} // namespace sgw
} // namespace tsc
